package example;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.TreeMap;
import org.pi4.locutil.MACAddress;

import org.pi4.locutil.io.TraceGenerator;
import org.pi4.locutil.trace.Parser;
import org.pi4.locutil.trace.SignalStrengthSamples;
import org.pi4.locutil.trace.TraceEntry;

/**
 * Example of how to use LocUtil
 * @author mikkelbk
 */

public class LocUtilExample {

	/**
	 * Execute example
	 * @param args
	 */
	public static void main(String[] args) {
		
		String offlinePath = "src/data/MU.1.5meters.offline.trace", onlinePath = "src/data/MU.1.5meters.online.trace";
		
		//Construct parsers
		File offlineFile = new File(offlinePath);
		Parser offlineParser = new Parser(offlineFile);
		//System.out.println("Offline File: " +  offlineFile.getAbsoluteFile());
		
		File onlineFile = new File(onlinePath);
		Parser onlineParser = new Parser(onlineFile);
		//System.out.println("Online File: " + onlineFile.getAbsoluteFile());
		
		//Construct trace generator
		TraceGenerator tg;
		try {
			int offlineSize = 25;
			int onlineSize = 5;
			tg = new TraceGenerator(offlineParser, onlineParser,offlineSize,onlineSize);
			
			//Generate traces from parsed files
			tg.generate();
			
			//Iterate the trace generated from the offline file
			List<TraceEntry> offlineTrace = tg.getOffline();
                        
                        HashMap<MACAddress, ArrayList<TraceEntry>> index = new HashMap<>();
                        
                        
                        
			for(TraceEntry entry: offlineTrace) {
				//Print out coordinates for the collection point and the number of signal strength samples
			
                            SignalStrengthSamples s = entry.getSignalStrengthSamples();
                            
                            for(MACAddress m : s.getSortedAccessPoints()) {
                                double signal = s.getAverageSignalStrength(m);
                                if(index.containsKey(m) == false) {
                                    index.put(m, new ArrayList<TraceEntry>());
                                }
                                index.get(m).add(entry);
                            }
                            
                            //System.out.println(entry.getGeoPosition().toString() + " - " + entry.getSignalStrengthSamples().size());				
			}
			
			//Iterate the trace generated from the online file
			List<TraceEntry> onlineTrace = tg.getOnline();			
			for(TraceEntry entry: onlineTrace) {
                            
                            HashSet<TraceEntry> entries = new HashSet();
                            
                            for(MACAddress m : entry.getSignalStrengthSamples().getSortedAccessPoints()) {
                                
                                if(index.containsKey(m))
                                {
                                    for(TraceEntry offlineEntry : index.get(m)) {
                                        if(entries.contains(offlineEntry) == false) {
                                            entries.add(offlineEntry);
                                        }
                                    }
                                }
                            }
                            
                            double minDistance = Double.MAX_VALUE;
                            TraceEntry bestEntry = null;
                            for(TraceEntry offline : entries) {
                                double distance = CalcDistance(offline, entry);
                                if(distance < minDistance) {
                                    bestEntry = offline;
                                    minDistance = distance;
                                }
                            }
                            
                            System.out.println("Estimated position: " + bestEntry.getGeoPosition().toString() + " True position: "+entry.getGeoPosition().toString());
                            
                            
                            
				//Print out coordinates for the collection point and the number of signal strength samples
				//System.out.println(entry.getGeoPosition().toString() + " - " + entry.getSignalStrengthSamples().size());
			}
			
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

        private static int NUMBER_OF_SAMPLES = 6;
        
        private static double CalcDistance(TraceEntry offline, TraceEntry online) {
            
            int i = 0; 
            
            double dist = 0;
            
            for(MACAddress mOnline : online.getSignalStrengthSamples().getSortedAccessPoints()) {
                
                if(i > NUMBER_OF_SAMPLES)
                    break;
                
                double signalStrengthOffline = 0;
                double signalStrengthOnline = 0;
                
                if(offline.getSignalStrengthSamples().containsKey(mOnline) == false) {
                dist = Double.MAX_VALUE;
                    break;
                }
                
                signalStrengthOffline = offline.getSignalStrengthSamples().getAverageSignalStrength(mOnline);
                signalStrengthOnline = online.getSignalStrengthSamples().getAverageSignalStrength(mOnline);

                //System.out.println("Dist " + dist);
                dist += Math.pow(signalStrengthOnline - signalStrengthOffline, 2);
                i++;
            }
            
            dist = Math.sqrt(dist);
            
            return dist;
        }
        
}
